package com.project.service.common;

import java.io.Serializable;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;

import javax.naming.NamingException;
import javax.servlet.ServletContext;

import org.apache.commons.logging.Log;

import com.project.common.Constants;
import com.project.common.ExceptionLogger;
import com.project.common.MemoryFactory;
import com.project.common.MemoryObject;
import com.project.common.PuduException;
import com.project.dao.impl.ConnectwithDB;
import com.project.service.ICommonService;
import com.project.webapp.form.BaseForm;

public abstract class CommonServiceImpl implements ICommonService, Serializable {
	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public Connection getConnectionSQL() throws NamingException, SQLException,
			PuduException {
		// JNDI连接
		//System.out.println("我进入了jndi连接池了");
		Connection con = ConnectwithDB
				.getConnection(Constants.PUDU_DATABASE_JNDI_MYSQL);
		try {
			con.setAutoCommit(false);
		} catch (SQLException e) {
			throw new PuduException(PuduException.EX_DB_CONNECTION, e);
		}
		return con;
	}

	/**
	 * descritpion: extends BaseService的Service要重載這個方法
	 * 
	 * @param form
	 *            baseform
	 * @param log
	 * @param con
	 * @return
	 * @throws Exception
	 */
	public List<BaseForm> queryImp(BaseForm form, Connection con, Log log)
			throws Exception {
		log.error("未实作queryImp(Connection con, BaseForm form,	Log log)方法");
		return null;
	}

	/**
	 * descritpion: extends BaseService的Service要重載這個方法
	 * 
	 * @param form
	 *            baseform
	 * @param log
	 * @param con
	 * @return
	 * @throws Exception
	 */
	public Object queryObjectImp(Connection con, Log log) throws Exception {
		log.error("未实作queryObjectImp(Connection con, BaseForm form, Agent agent, Log log)方法");
		return null;
	}
	
	/**
	 * form ：查询条件封装在form中
		log ：传入log用于按log4j的配置写log到指定的文档
		key ：保存在memory中的key值
		durSecond 过期时间，以秒记
		context 上下文环境
	 */
	@Override
	
	public List<BaseForm> query(BaseForm form, Log log, String key,
			int durSecond, ServletContext context) {
		//System.out.println("进入了这个方法。。");
		// 假如可以从memory取到，就返回，不读DB
		MemoryObject mo = MemoryFactory
				.getMemoryObject(key, durSecond, context);
		//判断一下mo是否为空,经过判断mo是为空的
		//System.out.println(mo);
		if (null != mo) {
			return (List<BaseForm>) mo.getObject();
		}
		List<BaseForm> list = null;
		Connection con = null;
		try {
			//得到连接
			con = this.getConnectionSQL();
			//System.out.println("con："+con);
			// System.out.println(form.getCountPerPage());
			list = queryImp(form, con, log);
			try {
				con.commit();
			} catch (SQLException e) {
				throw new PuduException(PuduException.EX_DB_OPERATION, e);
			}
		} catch (PuduException e) {
			e.printStackTrace();
			this.rollbackConnection(con, log);
			processException(e, log);
		} catch (Exception e) {
			e.printStackTrace();
			this.rollbackConnection(con, log);
			processException(e, log);
		} finally {
			this.closeConnection(con, log);
		}

		// 把返回list放入memory
		if (0 == durSecond) {
			mo = new MemoryObject();
			mo.setObject(list);
			MemoryFactory.putMemoryObject(key, mo, context);
		}
		
		return list;
	}

	public Object queryObject(BaseForm form, Log log) {
		Object rtnObj = null;
		Connection con = null;
		try {
			con = this.getConnectionSQL();
			rtnObj = queryObjectImp(con, log);
			try {
				con.commit();
			} catch (SQLException e) {
				throw new PuduException(PuduException.EX_DB_OPERATION, e);
			}
		} catch (PuduException e) {
			e.printStackTrace();
			this.rollbackConnection(con, log);
			processException(e, log);
		} catch (Exception e) {
			e.printStackTrace();
			this.rollbackConnection(con, log);
			processException(e, log);
		} finally {
			this.closeConnection(con, log);
		}
		return rtnObj;
	}

	/**
	 * description:rollback DB操作
	 * 
	 * @param con
	 *            DB連接
	 * @param log
	 */
	public void rollbackConnection(Connection con, Log log) {
		try {
			if (con != null) {
				if (!con.isClosed()) {
					con.rollback();
				}
			}
		} catch (SQLException e) {
			processException(new PuduException(PuduException.EX_DB_CONNECTION,
					e), log);
		}
	}

	/**
	 * description:關閉DB連接
	 * 
	 * @param con
	 *            DB連接
	 * @param log
	 */
	public void closeConnection(Connection con, Log log) {
		try {
			if (con != null) {
				if (!con.isClosed()) {
					con.close();
				}
				con = null;
			}
		} catch (SQLException e) {
			processException(new PuduException(PuduException.EX_DB_CONNECTION,
					e), log);
		}
	}

	/**
	 * descripton:所有的異常集中到Service層由此方法做集中處理
	 * 
	 * @param e
	 *            異常
	 * @param log
	 *            log
	 */
	@SuppressWarnings("unused")
	public static void processException(Exception e, Log log) {
		if (e instanceof PuduException) {
			PuduException puduException = (PuduException) e;
			if (0 == Constants.RUN_TIME_ENVIRONMENT) {
				// local端執行

				if (PuduException.EX_DB_OPERATION.equals(puduException
						.getPudu_exception_type())) {
					// DB操作異常，要列印SQL
					log.error("sql=" + puduException.getExMessage());
				}
				// 其它異常直接列印stackTrace
				e.printStackTrace();
				// ExceptionLogger.printExceptionStackTrace(e, log);
			} else {
				// remote端執行
				if (PuduException.EX_DB_OPERATION.equals(puduException
						.getPudu_exception_type())) {
					// DB操作異常，要列印SQL
					log.error("sql=" + puduException.getExMessage());
				}
				ExceptionLogger.printExceptionStackTrace(e, log);
			}
		} else {
			if ("0".equals(Constants.RUN_TIME_ENVIRONMENT)) {
				// local端執行
				e.printStackTrace();
			} else {
				// remote端執行
				ExceptionLogger.printExceptionStackTrace(e, log);
			}

		}
	}
}
